package com.dituhui.web;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.apache.log4j.Logger;

import com.dituhui.gps.service.GetTrack;
import com.dituhui.gps.vo.GPSLine;
import com.dituhui.tool.io.Constants;
import com.dituhui.tool.util.DateUtil;
import com.dituhui.tool.util.StringUtil;

/**
 * GPS轨迹查询服务
 * 
 * @author liweigu
 * 
 */
public class GPS extends HttpServlet {
	private static Logger LOGGER = Logger.getLogger(GetTrack.class);
	static String kafkaUrl;
	static String kafkaTopic = "GPS";
	private String redisUrl;
	private int redisPort;
	private String redisPwd;
	private String historyESUrl;

	public void init() throws ServletException {
		kafkaUrl = Constants.getValue("kafkaUrl");
		LOGGER.info("kafkaUrl=" + kafkaUrl);
		redisUrl = Constants.getValue("REDIS.HOST", "gps_config.properties");
		redisPort = Integer.parseInt(Constants.getValue("REDIS.PORT", "gps_config.properties"));
		redisPwd = Constants.getValue("REDIS.PWD", "gps_config.properties");
		LOGGER.info("redisUrl=" + redisUrl);
		// LOGGER.info("redisPwd=" + redisPwd);
		this.historyESUrl = Constants.getValue("HistoryESUrl", "gps_config.properties");
		LOGGER.info("historyESUrl=" + this.historyESUrl);
	}

	// http://ip:port/wxweb/gps
	public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		String accountId = request.getParameter("a");
		String groupId = request.getParameter("g");
		if (groupId == null || groupId.length() == 0 || groupId.equals(StringUtil.NULL)) {
			// 空值置为null
			groupId = null;
		}
		String strStartTime = request.getParameter("start");
		Date todayDate = new Date();
		SimpleDateFormat dayFormat = DateUtil.getDayFormat();
		if (strStartTime == null || strStartTime.length() == 0) {
			strStartTime = dayFormat.format(todayDate);
		}
		// System.out.println("strStartTime="+ strStartTime);
		String strEndTime = request.getParameter("end");
		if (strEndTime == null || strEndTime.length() == 0) {
			strEndTime = dayFormat.format(todayDate);
		}
		// System.out.println("strEndTime="+ strEndTime);
		// 跨域访问
		String callbacks = (request.getParameter("callbacks") != null) ? request.getParameter("callbacks") : null;
		response.setCharacterEncoding("UTF-8");
		PrintWriter out = response.getWriter();
		if (accountId == null) {
			out.print("参数a非法，应传入accountId");
		} else {
			// 当天日期
			String strTodayDate = dayFormat.format(todayDate);
			// TODO: 还需处理开始日期比当天更晚的情况，以及开始日期比结束日期晚的情况
			Date endDate = null;
			if (strEndTime != null && strEndTime.length() > 0) {
				try {
					endDate = dayFormat.parse(strEndTime);
					// 如果结束日期晚于“今天”，则设值为“今天”。
					// 虽然endDate的精度是年月日，仍然可以跟nowDate进行有效比较。
					int result = endDate.compareTo(todayDate);
					if (result > 0) {
						// todayDate的精度是年月日时分秒，但不影响程序逻辑，因此这里不做精度转换。
						endDate = todayDate;
					}
				} catch (ParseException e) {
					String message = "解析strEndTime（" + strEndTime + "）发生异常。";
					LOGGER.debug(message, e);
				} catch (NumberFormatException e) {
					String message = "解析strEndTime（" + strEndTime + "）发生异常。";
					LOGGER.debug(message, e);
				}
			}

			// 是否需要查询当天
			// 如果结束日期或开始日期是当天，则设置isQueryToday为true
			boolean isQueryToday = (strTodayDate.equals(strEndTime) || (strTodayDate.equals(strStartTime)));
			// System.out.println("isQueryToday =" + isQueryToday);

			List<Map<String, String>> gpsData = new ArrayList<Map<String, String>>();

			// 查询历史
			boolean searchHistory = true;
			if (strTodayDate.equals(strStartTime) || (strStartTime == null) || (strStartTime.length() == 0)) {
				// 如果起始时间是“今天”，则不查询历史数据时，把searchHistory设置为false。
				searchHistory = false;
			}
			// 根据时间跨度构建查询索引
			if (endDate != null) {
				// 查询历史数据时使用的日期范围不包含当天
				// 当开始日期不是当天、结束日期是当天时
				if (!strTodayDate.equals(strStartTime) && strTodayDate.equals(strEndTime)) {
					// 把结束日期设为“今天”的前一天，因为查历史数据是不查询当天的。
					// 进入此分支时，开始日期不会是当天。
					endDate = DateUtil.getPreviousDate(endDate);
					strEndTime = dayFormat.format(endDate);
				}
			} else {
				// endDate为null时，不需要根据是否是当天去修改endDate。
			}
			if (searchHistory) {
				// seacrhHistory允许strEndTime为空
				try {
					Map<String, String> datas = GetTrack.getGPSLineFromHistoryES(accountId, groupId, strStartTime, strEndTime, this.historyESUrl);
					List<String> dates = new ArrayList<String>();
					if (datas != null) {
						for (String date : datas.keySet()) {
							dates.add(date);
						}
						Collections.sort(dates);
						for (String date : dates) {
							HashMap<String, String> data = new HashMap<String, String>();
							data.put(date, datas.get(date));
							gpsData.add(data);
						}
					}
				} catch (Exception e) {
					String message = "seacrhHistory发生异常。";
					LOGGER.warn(message, e);
					// e.printStackTrace();
				}
				// System.out.println(gpsData);
			}

			// 查询当天
			if (isQueryToday) {
				try {
					boolean sortByTime = true;
					GPSLine gpsLine = GetTrack.getGPSLineFromRedis(redisUrl, redisPort, redisPwd, accountId, groupId, sortByTime);
					if (gpsLine != null) {
						// LOGGER.info("(getGPSLineFromRedis)gpsLine=" + gpsLine.toCSVString());
						Map<String, String> todayData = new HashMap<String, String>();
						todayData.put(strTodayDate, gpsLine.toCSVString());
						// 当天的添加到最前面
						gpsData.add(0, todayData);
					}
				} catch (Exception e) {
					String message = "seacrhRealtime发生异常。";
					LOGGER.warn(message, e);
					// e.printStackTrace();
				}
			}

			StringBuilder content = new StringBuilder();
			int i = 0;
			if (gpsData.size() > 0) {
				for (Map<String, String> data : gpsData) {
					for (String date : data.keySet()) {
						if (i++ > 0) {
							content.append(StringUtil.AngularBracket);
							content.append(StringUtil.AngularBracket);
						}
						content.append(date + StringUtil.AngularBracket + data.get(date));
					}
				}
			} else {
				content.append("NoData");
			}
			StringBuilder output = new StringBuilder();
			if (callbacks != null && callbacks.length() > 0) {
				output.append(callbacks);
				output.append("(");
				JSONObject jsonObject = new JSONObject();
				jsonObject.put("data", content.toString());
				output.append(jsonObject.toString());
				output.append(")");
			} else {
				output.append(content);
			}
			out.print(output.toString());
			out.flush();
			out.close();
		}
	}
}
